//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

namespace Microsoft.Research.eResearch.Blackboard.Wcf
{
    using System;
    using System.ServiceModel;
    using Microsoft.Research.eResearch.Blackboard.Common;

    /// <summary>
    /// Provides an extension that the WCF ServiceHost can use to expose the single Blackboard instance to 
    /// multiple instances of the <see cref="WcfPublisherMessageService"/> service. 
    /// </summary>
    public class PublisherMessageReceiverExtension : IExtension<ServiceHostBase>
    {
        /// <summary>
        /// Method to be executed whenever blackboard message is received.
        /// </summary>
        private Action<BlackboardMessage> onBlackboardMessageReceived;

        /// <summary>
        /// Method to be executed whenever publisher is registered.
        /// </summary>
        private Func<Uri, SubscriptionProfile> onPublisherRegistering;

        /// <summary>
        /// Method to be executed whenever publisher is un-registered.
        /// </summary>
        private Action<Uri> onPublisherUnregistering;

        /// <summary>
        /// Initializes a new instance of the <see cref="PublisherMessageReceiverExtension"/> class.
        /// </summary>
        /// <param name="onPublisherRegistering">A delegate specifying the method to call when the Register method is called.</param>
        /// <param name="onPublisherUnregistering">A delegate specifying the method to call when the Unregister method is called.</param>
        /// <param name="onBlackboardMessageReceived">A delegate specifying the method to call when the Publish method is called.</param>
        public PublisherMessageReceiverExtension(
            Func<Uri, SubscriptionProfile> onPublisherRegistering,
            Action<Uri> onPublisherUnregistering,
            Action<BlackboardMessage> onBlackboardMessageReceived)
        {
            if (onPublisherRegistering == null)
            {
                throw new ArgumentNullException("onPublisherRegistering");
            }

            if (onPublisherUnregistering == null)
            {
                throw new ArgumentNullException("onPublisherUnregistering");
            }

            if (onBlackboardMessageReceived == null)
            {
                throw new ArgumentNullException("onBlackboardMessageReceived");
            }

            this.onPublisherRegistering = onPublisherRegistering;
            this.onPublisherUnregistering = onPublisherUnregistering;
            this.onBlackboardMessageReceived = onBlackboardMessageReceived;
        } 

        /// <summary>
        /// Publishes the specified message to the blackboard.
        /// </summary>
        /// <param name="message">The blackboard message.</param>
        public void Publish(BlackboardMessage message)
        {
            onBlackboardMessageReceived(message);
        } 

        /// <summary>
        /// Registers the specified return address of the publisher with the blackboard.
        /// </summary>
        /// <param name="returnAddress">The return address of the publisher.</param>
        /// <returns>The publisher's initial subscription profile.</returns>
        public SubscriptionProfile Register(Uri returnAddress)
        {
            return onPublisherRegistering(returnAddress);
        } 

        /// <summary>
        /// Unregisters the specified return address of the publisher from the blackboard.
        /// </summary>
        /// <param name="returnAddress">The return address of the publisher.</param>
        public void Unregister(Uri returnAddress)
        {
            onPublisherUnregistering(returnAddress);
        } 

        /// <summary>
        /// Enables an extension object to find out when it has been aggregated. Called when the 
        /// extension is added to the <see cref="P:System.ServiceModel.IExtensibleObject`1.Extensions"/> property.
        /// </summary>
        /// <param name="owner">The extensible object that aggregates this extension.</param>
        public void Attach(ServiceHostBase owner)
        {
        } 

        /// <summary>
        /// Enables an object to find out when it is no longer aggregated. Called when an extension
        /// is removed from the <see cref="P:System.ServiceModel.IExtensibleObject`1.Extensions"/> property.
        /// </summary>
        /// <param name="owner">The extensible object that aggregates this extension.</param>
        public void Detach(ServiceHostBase owner)
        {
        } 
    }
}
